#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include <queue> //队列
#include <semaphore.h>

using namespace std;
#define NUM 6

template<typename T>
class RingQueue{
  private:
    vector<T> q;
    int cap;
    sem_t data_sem;
    sem_t space_sem;
    int consumer_pos;
    int producer_pos;

  private:
    void P(sem_t &s)
    {
      sem_wait(&s);
    }

    void V(sem_t &s)
    {
      sem_post(&s);
    }

  public:
    RingQueue(int _cap = NUM)
      :q(_cap)
      ,cap(_cap)
       ,consumer_pos(0)
       ,producer_pos(0)
    {
      q.resize(cap);
      sem_init(&data_sem, 0, 0); // 开始数据资源为空，设为0
      sem_init(&space_sem, 0, cap);// cap表示空格资源个数，设为cap容量

    }

    void Push(const T& in)
    {
      //生产者，获取空格资源
      P(space_sem);
      //sem_wait(&space_sem); // P
      //P 申请资源
      q[producer_pos] = in;
      V(data_sem);
      //V 释放资源
      
      producer_pos++;
      producer_pos %= cap;
    }

    void Pop(T& out)
    {
      P(data_sem);//消费者关注数据资源
      out= q[consumer_pos];
      V(space_sem);//取走数据，剩下空格，空格多了

      consumer_pos++;
      consumer_pos %= cap;
    }

    ~RingQueue()
    {
      sem_destroy(&data_sem);
      sem_destroy(&space_sem);
    }
};

//void *consumer(void* arg)
//{
//  RingQueue *bq = (RingQueue*) arg;
//  int data;
//  while(1){
//    bq->PopData(data);
//    cout<<"消费者 : " << data << endl;
//  }
//}
//
//void *producer(void *arg)
//{
//  RingQueue *bq = (RingQueue*) arg;
//  srand((unsigned long)time(NULL)); //随机数种子
//  while(1){
//    int data = rand()%10;
//    bq->PushData(data);
//    cout<<"生产者 : "<< data << endl;
//  }
//}
//
//int main()
//{
//  RingQueue bq;
//  pthread_t c,p;
//  pthread_create(&c, NULL, consumer, (void*)&bq);
//  pthread_create(&p, NULL, producer, (void*)&bq);
//
//  pthread_join(c, NULL);
//  pthread_join(p, NULL);
//  return 20;
//}
